/*
 * Copyright (c) 2001, Aslak Hellesøy, BEKK Consulting
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * - Redistributions of source code must retain the above copyright notice,
 *   this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above copyright
 *   notice, this list of conditions and the following disclaimer in the
 *   documentation and/or other materials provided with the distribution.
 *
 * - Neither the name of BEKK Consulting nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 */
package middlegen.plugins.entitybean.swing;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import middlegen.Column;
import middlegen.javax.JavaColumn;
import middlegen.javax.Sql2Java;
import middlegen.swing.JColumnSettingsPanel;

/**
 * <Describe class>
 *
 * @author <a href="mailto:eivind.waaler@bekk.no">Eivind Waaler</a>
 * @created 11. november 2005
 * @version $Id: JEntityColumnSettingsPanel.java,v 1.1 2005/11/12 02:53:40 eivindw Exp $
 */
public class JEntityColumnSettingsPanel extends JColumnSettingsPanel {

   /**
    * @todo-javadoc Describe the column
    */
   protected JLabel _columnNameLabel;

   /**
    * @todo-javadoc Describe the column
    */
   protected JTextField _columnNameField;

   /**
    * @todo-javadoc Describe the column
    */
   protected JLabel _columnTypeLabel;

   /**
    * @todo-javadoc Describe the column
    */
   protected JComboBox _columnTypeCombo;

   /**
    * @todo-javadoc Describe the column
    */
   protected JavaColumn[] _currentColumns;

   /**
    * @todo-javadoc Describe the column
    */
   protected final DocumentListener _documentListener =
      new DocumentListener() {
         public void changedUpdate(DocumentEvent event) {
            update();
         }


         public void insertUpdate(DocumentEvent event) {
            update();
         }


         public void removeUpdate(DocumentEvent event) {
            update();
         }


         private void update() {
            if (_currentColumns.length > 0) {
               updateColumn(_columnNameField.getText(), _currentColumns[0].getJavaType());
            }
         }
      };

   /**
    * @todo-javadoc Describe the column
    */
   protected final ActionListener _comboListener =
      new ActionListener() {
         public void actionPerformed(ActionEvent event) {
            update();
         }


         private void update() {
            for (int i = 0; i < _currentColumns.length; i++) {
               String type = (String) _columnTypeCombo.getSelectedItem();
               if (type != null) {
                  updateColumn(_currentColumns[i].getVariableName(), type);
               }
            }
         }
      };

   /**
    * Describe what the JEntityColumnSettingsPanel constructor does
    *
    * @todo-javadoc Write javadocs for constructor
    */
   public JEntityColumnSettingsPanel() {
      super();

      GridLayout layout = new GridLayout(0, 2);
      setLayout(layout);

      initComponents();
      addComponents();

      // register listeners on text column and combo that will update borders
      _columnNameField.getDocument().addDocumentListener(_documentListener);
      _columnTypeCombo.addActionListener(_comboListener);
   }

   /**
    * Sets the Column attribute of the JColumnSettingsPanel object
    *
    * @todo fixme
    * @param columns The new Columns value
    */
   public void setColumns(Column[] columns) {
      _currentColumns = new JavaColumn[columns.length];
      for (int i = 0; i < columns.length; i++) {
         _currentColumns[i] = (JavaColumn) columns[i];
      }

      if (_currentColumns.length == 1) {
         // single selection
         _columnNameField.setText(_currentColumns[0].getVariableName());
         _columnNameField.setEnabled(true);
      }
      else {
         _columnNameField.setText("");
         _columnNameField.setEnabled(false);
      }

      String selectedJavaType = _currentColumns[0].getJavaType();
      Object[][] arrays = new Object[_currentColumns.length][];
      for (int i = 0; i < _currentColumns.length; i++) {
         arrays[i] = Sql2Java.getJavaTypes(_currentColumns[i].getSqlType());
         String javaType = _currentColumns[i].getJavaType();
         if (!javaType.equals(selectedJavaType)) {
            selectedJavaType = "";
         }
      }
      Object[] common = common(arrays);
      ComboBoxModel model = new DefaultComboBoxModel(common);
      _columnTypeCombo.setModel(model);
      _columnTypeCombo.setSelectedItem(selectedJavaType);
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method
    */
   protected void initComponents() {
      _columnNameLabel = new JLabel("Java property name");
      _columnNameField = new JTextField();
      _columnTypeLabel = new JLabel("Java type");
      _columnTypeCombo = new JComboBox();
   }

   /**
    * Describe the method
    *
    * @todo-javadoc Describe the method
    */
   protected void addComponents() {
      GridLayout layout = new GridLayout(0, 2, 4, 8);
      setLayout(layout);
      add(_columnNameLabel);
      add(_columnNameField);
      add(_columnTypeLabel);
      add(_columnTypeCombo);
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for method
    * @param propertyName Describe what the parameter does
    * @param javaType Describe what the parameter does
    */
   protected void updateColumn(String propertyName, String javaType) {
      for (int i = 0; i < _currentColumns.length; i++) {
         _currentColumns[i].setJavaType(javaType);
      }
      if (_currentColumns.length == 1) {
         _currentColumns[0].setVariableName(propertyName);
      }
   }

   /**
    * Describe what the method does
    *
    * @todo-javadoc Write javadocs for method
    * @todo-javadoc Write javadocs for method parameter
    * @todo-javadoc Write javadocs for return value
    * @param arrays Describe what the parameter does
    * @return Describe the return value
    */
   private Object[] common(Object[][] arrays) {
      HashMap union = new HashMap();
      for (int i = 0; i < arrays.length; i++) {
         Object[] array = arrays[i];
         for (int j = 0; j < array.length; j++) {
            Integer occurrances = (Integer) union.get(array[j]);
            if (occurrances == null) {
               occurrances = new Integer(0);
            }
            union.put(array[j], new Integer(occurrances.intValue() + 1));
         }
      }
      ArrayList common = new ArrayList();
      if (arrays.length > 1) {
         common.add("");
      }
      Iterator iterator = union.entrySet().iterator();
      while (iterator.hasNext()) {
         Map.Entry entry = (Map.Entry) iterator.next();
         Integer occurrances = (Integer) entry.getValue();
         if (occurrances.intValue() == arrays.length) {
            common.add(entry.getKey());
         }
      }
      Object[] result = common.toArray();
      Arrays.sort(result, Sql2Java.getTypeComparator());
      return result;
   }
}
